home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / bin / ecryptfs-setup-private < prev    next >
Encoding:
Text File  |  2009-06-04  |  14.7 KB  |  462 lines

  1. #!/bin/sh
  2. # This script sets up an ecryptfs mount in a user's ~/Private
  3. #
  4. # Originally ecryptfs-setup-pam-wrapped.sh by Michael Halcrow, IBM
  5. #
  6. # Ported for use on Ubuntu by Dustin Kirkland <kirkland@canonical.com>
  7. # Copyright (C) 2008 Canonical Ltd.
  8. # Copyright (C) 2007-2008 International Business Machines
  9. PRIVATE_DIR="Private"
  10. WRAPPING_PASS="LOGIN"
  11. PW_ATTEMPTS=3
  12. MESSAGE="Enter your login passphrase"
  13. CIPHER="aes"
  14. KEYBYTES="16"
  15. FNEK=
  16.  
  17. # Zero out user-defined GREP_OPTIONS, such as --line-number
  18. GREP_OPTIONS=
  19.  
  20. usage() {
  21.     echo
  22.     echo "Usage:"
  23.     echo "  $0 [-f|--force] [-w|--wrapping] [--nopwcheck] [-n|--no-fnek]"
  24.     echo "  [-u|--username USER] [-l|--loginpass LOGINPASS]"
  25.     echo "  [-m|--mountpass MOUNTPASS]"
  26.     echo
  27.     echo " -f, --force      Force overwriting of an existing setup"
  28.     echo " -w, --wrapping   Use an independent wrapping passphrase,"
  29.     echo "                  different from the login passphrase"
  30.     echo " -n, --no-fnek    Do not encrypt filenames; If this flag is"
  31.     echo "                  omitted, and the kernel supports filename"
  32.     echo "                  encryption, then filenames will be encrypted"
  33.     echo " -u, --username   Username for encrypted private mountpoint,"
  34.     echo "                  defaults to yourself"
  35.     echo " -l, --loginpass  Login/Wrapping passphrase for USER,"
  36.     echo "                  used to wrap MOUNTPASS"
  37.     echo " --nopwcheck      Do not check the validity of the specified"
  38.     echo "                  login password (useful for LDAP user accounts)"
  39.     echo " --noautomount    Setup this user such that the encrypted private"
  40.     echo "                  directory is not automatically mounted on login"
  41.     echo " --noautoumount   Setup this user such that the encrypted private"
  42.     echo "                  directory is not automatically unmounted at"
  43.     echo "                  logout"
  44.     echo " -m, --mountpass  Passphrase for mounting the ecryptfs directory,"
  45.     echo "                  defaults to randomly generated $KEYBYTES bytes"
  46.     echo " -b, --bootstrap  Bootstrap a new user's entire home directory"
  47.     echo "                  Generates a random mount passphrase, which"
  48.     echo "            will be wrapped when the new login passphrase"
  49.     echo "            is set. SHOULD ONLY BE CALLED FROM 'adduser'."
  50.     echo " --undo           Provide instructions on how to undo an"
  51.     echo "                  encrypted private setup"
  52.     echo
  53.     echo "   Be sure to properly escape your parameters according to your"
  54.     echo "   shell's special character nuances, and also surround the"
  55.     echo "   parameters by double quotes, if necessary."
  56.     echo
  57.     exit 1
  58. }
  59.  
  60. undo_msg() {
  61.     echo "
  62. In the event that you want to remove your eCryptfs Private Directory setup,
  63. you will need to very carefully perform the following actions manually:
  64.  
  65.  1. Obtain your Private directory mountpoint
  66.    $ PRIVATE=\`cat ~/.ecryptfs/Private.mnt 2>/dev/null || echo \$HOME/Private\`
  67.  2. Ensure that you have moved all relevant data out of your \$PRIVATE directory
  68.  3. Unmount your encrypted private directory
  69.    $ ecryptfs-umount-private
  70.  4. Make your Private directory writable again
  71.    $ chmod 700 \$PRIVATE
  72.  5. Remove \$PRIVATE, ~/.Private, ~/.ecryptfs
  73.     Note: THIS IS VERY PERMANENT, BE VERY CAREFUL
  74.    $ rm -rf \$PRIVATE ~/.Private ~/.ecryptfs
  75.  6. Uninstall the utilities (this is specific to your Linux distribution)
  76.    $ sudo apt-get remove ecryptfs-utils libecryptfs0
  77. "
  78. }
  79.  
  80. error() {
  81.     echo "ERROR: $1" 1>&2
  82.     exit 1
  83. }
  84.  
  85. error_testing() {
  86.     rm -f "$1" >/dev/null
  87.     /sbin/umount.ecryptfs_private >/dev/null
  88.     error "$2"
  89.     exit 1
  90. }
  91.  
  92. random_passphrase () {
  93.     bytes=$1
  94.     # Pull $1 of random data from /dev/urandom,
  95.     # and convert to a string of hex digits
  96.     od -x -N $bytes --width=$bytes /dev/urandom | head -n 1 | sed "s/^0000000//" | sed "s/\s*//g"
  97. }
  98.  
  99. filename_encryption_available() {
  100.     version=$(cat /sys/fs/ecryptfs/version 2>/dev/null)
  101.     [ -z "$version" ] && error "Can't get ecryptfs version, ecryptfs kernel module not loaded?"
  102.     [ $(($version & 0x100)) -eq 0 ] && return 1
  103.     return 0
  104. }
  105.  
  106. filename_encryption_available && FNEK="--fnek"
  107.  
  108. if [ ! -z "$SUDO_USER" ]; then
  109.     USER="$SUDO_USER"
  110. fi
  111.  
  112. while [ ! -z "$1" ]; do
  113.     case "$1" in
  114.         -u|--username)
  115.                         USER="$2"
  116.             shift 2
  117.         ;;
  118.         -l|--loginpass)
  119.             LOGINPASS="$2"
  120.             shift 2
  121.         ;;
  122.         -m|--mountpass)
  123.             MOUNTPASS="$2"
  124.             shift 2
  125.         ;;
  126.         -w|--wrapping)
  127.             WRAPPING_PASS="INDEPENDENT"
  128.             MESSAGE="Enter your wrapping passphrase"
  129.             shift 1
  130.         ;;
  131.         -f|--force)
  132.             FORCE=1
  133.             shift 1
  134.         ;;
  135.         --nopwcheck)
  136.             NOPWCHECK=1
  137.             shift 1
  138.         ;;
  139.         --noautomount)
  140.             NOAUTOMOUNT=1
  141.             shift 1
  142.         ;;
  143.         --noautoumount)
  144.             NOAUTOUMOUNT=1
  145.             shift 1
  146.         ;;
  147.         --undo)
  148.             undo_msg
  149.             exit 0
  150.         ;;
  151.         -b|--bootstrap)
  152.             [ `whoami` = "root" ] || error "You must be root to bootstrap encrypt a home directory"
  153.             BOOTSTRAP=1
  154.             MOUNTPASS=`random_passphrase $KEYBYTES`
  155.             RANDOM_MOUNTPASS=1
  156.             shift 1
  157.         ;;
  158.         -n|--no-fnek)
  159.             FNEK=
  160.             shift 1
  161.         ;;
  162.         *)
  163.             usage
  164.         ;;
  165.     esac
  166. done
  167.  
  168. # Prompt for the USER name, if not on the command line and not in the env
  169. if [ -z "$USER" ]; then
  170.     while [ true ]; do
  171.         echo -n "Enter the username: "
  172.         USER=`head -n1`
  173.         echo
  174.         if [ -z "$USER" ]; then
  175.             echo "ERROR: You must provide a username"
  176.             continue
  177.         else
  178.             # Verify that the user exists
  179.             if ! id "$USER" >/dev/null; then
  180.                 echo "ERROR: User [$USER] does not exist"
  181.                 continue
  182.             fi
  183.             break
  184.         fi
  185.     done
  186. else
  187.     # Verify that the user exists
  188.     id "$USER" >/dev/null || error "User [$USER] does not exist"
  189. fi
  190.  
  191. # Obtain the user's home directory
  192. HOME=`getent passwd "$USER" | awk -F: '{print $6}'`
  193. if [ ! -d "$HOME" ]; then
  194.     error "User home directory [$HOME] does not exist"
  195. fi
  196.  
  197. if [ "$BOOTSTRAP" = "1" ]; then
  198.     # If we want to encrypt the entire homedir, we need the .ecryptfs
  199.     # config dir elsewhere, but linked into the homedir
  200.     mkdir -p -m 700 /var/lib/ecryptfs/$USER
  201.     ln -sf /var/lib/ecryptfs/$USER $HOME/.ecryptfs
  202.     MOUNTPOINT="$HOME"
  203. else
  204.     mkdir -m 700 $HOME/.ecryptfs
  205.     MOUNTPOINT="$HOME/$PRIVATE_DIR"
  206. fi
  207.  
  208. # Check for previously setup private directory
  209. if [ -s "$HOME/.ecryptfs/wrapped-passphrase" -a "$FORCE" != "1" ]; then
  210.     error "wrapped-passphrase file already exists, use --force to overwrite."
  211. fi
  212. if [ -s "$HOME/.ecryptfs/$PRIVATE_DIR.sig" -a "$FORCE" != "1" ]; then
  213.     error "$PRIVATE_DIR.sig file already exists, use --force to overwrite."
  214. fi
  215.  
  216. # Check for active mounts
  217. CRYPTDIR="$HOME/.$PRIVATE_DIR"
  218. grep -qs "$MOUNTPOINT " /proc/mounts && error "[$MOUNTPOINT] is already mounted"
  219. grep -qs "$CRYPTDIR " /proc/mounts && error "[$CRYPTDIR] is already mounted"
  220.  
  221. # Check that the mount point and encrypted directory are empty (skip symlinks).
  222. # Perhaps one day we could provide a migration mode (using rsync or something),
  223. # but this would be VERY hard to do safely.
  224. count=`ls -Al "$MOUNTPOINT" 2>/dev/null | egrep -c "^[drwx-]{10}"`
  225. if [ "$count" != "0" ]; then
  226.     error "$MOUNTPOINT must be empty before proceeding"
  227. fi
  228. count=`ls -Al "$CRYPTDIR" 2>/dev/null | egrep -c "^[dlrwx-]{10}"`
  229. if [ "$count" != "0" ]; then
  230.     error "$CRYPTDIR must be empty before proceeding"
  231. fi
  232.  
  233. stty_orig=`stty -g`
  234. # Prompt for the LOGINPASS, if not on the command line and not in the env
  235. if [ -z "$LOGINPASS" ] && [ "$BOOTSTRAP" != "1" ]; then
  236.     tries=0
  237.     while [ $tries -lt $PW_ATTEMPTS ]; do
  238.         stty -echo
  239.         echo -n "$MESSAGE: "
  240.         LOGINPASS=`head -n1`
  241.         stty $stty_orig
  242.         echo
  243.         if [ $WRAPPING_PASS != "LOGIN" ]; then
  244.             stty -echo
  245.             echo -n "$MESSAGE (again): "
  246.             LOGINPASS2=`head -n1`
  247.             stty $stty_orig
  248.             echo
  249.             if [ "$LOGINPASS" != "$LOGINPASS2" ]; then
  250.                 echo "ERROR: Wrapping passphrases must match"
  251.             else
  252.                 break
  253.             fi
  254.             tries=$(($tries + 1))
  255.             continue
  256.         fi
  257.         if [ -z "$LOGINPASS" ]; then
  258.             echo "ERROR: You must provide a login passphrase"
  259.             tries=$(($tries + 1))
  260.         else
  261.             if [ "$NOPWCHECK" = "1" ]; then
  262.                 echo "INFO: Skipping password verification"
  263.                 break
  264.             else
  265.                 if printf "%s\0" "$LOGINPASS" | /sbin/unix_chkpwd "$USER" nullok; then
  266.                     break
  267.                 else
  268.                     echo "ERROR: Your login passphrase is incorrect"
  269.                     tries=$(($tries + 1))
  270.                 fi
  271.             fi
  272.         fi
  273.     done
  274.     if [ $tries -ge $PW_ATTEMPTS ]; then
  275.         echo "ERROR: Too many incorrect password attempts, exiting"
  276.         exit 1
  277.     fi
  278. fi
  279.  
  280. # Prompt for the MOUNTPASS, if not on the command line and not in the env
  281. if [ -z "$MOUNTPASS" ]; then
  282.     tries=0
  283.     while [ $tries -lt $PW_ATTEMPTS ]; do
  284.         stty -echo
  285.         echo -n "Enter your mount passphrase [leave blank to generate one]: "
  286.         MOUNTPASS=`head -n1`
  287.         stty $stty_orig
  288.         echo
  289.         if [ -z "$MOUNTPASS" ]; then
  290.             MOUNTPASS=`random_passphrase $KEYBYTES`
  291.             RANDOM_MOUNTPASS=1
  292.             break
  293.         else
  294.             stty -echo
  295.             echo -n "Enter your mount passphrase (again): "
  296.             MOUNTPASS2=`head -n1`
  297.             stty $stty_orig
  298.             echo
  299.             if [ "$MOUNTPASS" != "$MOUNTPASS2" ]; then
  300.                 echo "ERROR: Mount passphrases do not match"
  301.                 tries=$(($tries + 1))
  302.             else
  303.                 break
  304.             fi
  305.         fi
  306.     done
  307.     if [ $tries -ge $PW_ATTEMPTS ]; then
  308.         echo "ERROR: Too many incorrect passphrase attempts, exiting"
  309.         exit 1
  310.     fi
  311. fi
  312.  
  313. #echo
  314. #echo "Using username [$USER]"
  315. #echo "Using mount passphrase [$MOUNTPASS]"
  316. #echo "Using login passphrase [$LOGINPASS]"
  317. #echo "Using mount point [$MOUNTPOINT]"
  318. #echo "Using encrypted dir [$CRYPTDIR]"
  319. #echo
  320. #echo "This script will attempt to set up your system to mount"
  321. #echo "$MOUNTPOINT with eCryptfs automatically on login,"
  322. #echo "using your login passphrase."
  323. echo
  324. echo "************************************************************************"
  325. if [ "$RANDOM_MOUNTPASS" = "1" ] && [ "$BOOTSTRAP" != "1" ]; then
  326.     echo "YOU SHOULD RECORD THIS MOUNT PASSPHRASE AND STORE IN A SAFE LOCATION:"
  327.     echo "$MOUNTPASS"
  328. else
  329.     echo "YOU SHOULD RECORD YOUR MOUNT PASSPHRASE AND STORE IN A SAFE LOCATION:"
  330. fi
  331. echo "THIS WILL BE REQUIRED IF YOU NEED TO RECOVER YOUR DATA AT A LATER TIME."
  332. echo "************************************************************************"
  333. echo
  334.  
  335. ###############################################################################
  336.  
  337. # Setup private directory in home
  338. mkdir -m 700 -p "$CRYPTDIR" || error "Could not create crypt directory [$CRYPTDIR]"
  339. mkdir -m 700 -p "$MOUNTPOINT" || error "Could not create mount directory [$MOUNTPOINT]"
  340. ln -sf /usr/share/ecryptfs-utils/ecryptfs-mount-private.txt "$MOUNTPOINT"/README.txt
  341. ln -sf /usr/share/ecryptfs-utils/ecryptfs-mount-private.desktop "$MOUNTPOINT"/Access-Your-Private-Data.desktop
  342. chmod 500 "$MOUNTPOINT"
  343.  
  344. # Setup ~/.ecryptfs directory
  345. if [ "$NOAUTOMOUNT" = "1" ]; then
  346.     echo "INFO: $HOME/$PRIVATE_DIR will not be mounted on login"
  347. else
  348.     touch $HOME/.ecryptfs/auto-mount || error "Could not setup ecryptfs auto-mount"
  349. fi
  350. if [ "$NOAUTOUMOUNT" = "1" ]; then
  351.     echo "INFO: $HOME/$PRIVATE_DIR will not be unmounted on logout"
  352. else
  353.     touch $HOME/.ecryptfs/auto-umount || error "Could not setup ecryptfs auto-umount"
  354. fi
  355.  
  356. if [ "$WRAPPING_PASS" = "LOGIN" ]; then
  357.     rm -f $HOME/.ecryptfs/wrapping-independent || error "Could not remove ecryptfs wrapping-independent"
  358. else
  359.     touch $HOME/.ecryptfs/wrapping-independent || error "Could not setup ecryptfs wrapping-independent"
  360. fi
  361.  
  362.  
  363. # Backup any existing wrapped-passphrase or sig files; we DO NOT destroy this
  364. timestamp=`date +%Y%m%d%H%M%S`
  365. for i in "$HOME/.ecryptfs/wrapped-passphrase" "$HOME/.ecryptfs/$PRIVATE_DIR.sig"; do
  366.     if [ -s "$i" ]; then
  367.         mv -f "$i" "$i.$timestamp" || error "Could not backup existing data [$i]"
  368.     fi
  369. done
  370.  
  371. # Setup wrapped-passphrase file
  372. u=`umask`
  373. umask 377
  374. if [ "$BOOTSTRAP" = "1" ]; then
  375.     # This will be wrapped by pam_ecryptfs's chauthtok as soon as the user
  376.     # chooses a password.  Until that happens (hopefully soon), standard
  377.     # file permissions (600) are all that's protecting it.  Write it to
  378.     # ramdisk, to keep it from leaking to the hard-drive.
  379.     temp=`mktemp /dev/shm/.ecryptfs-XXXXXX`
  380.     printf "%s" "$MOUNTPASS" > "$temp"
  381.     mv "$temp" "/dev/shm/.ecryptfs-$USER"
  382. else
  383.     printf "%s\n%s" "$MOUNTPASS" "$LOGINPASS" | ecryptfs-wrap-passphrase "$HOME/.ecryptfs/wrapped-passphrase" - || error "Could not wrap passphrase"
  384. fi
  385. umask $u
  386.  
  387. # Add the passphrase to current keyring
  388. # On subsequent logins, this should be handled by "pam_ecryptfs.so unwrap"
  389. response=`printf "%s" "$MOUNTPASS" | ecryptfs-add-passphrase $FNEK -`
  390. if [ $? -ne 0 ]; then
  391.     error "Could not add passphrase to the current keyring"
  392. fi
  393. sig=`echo "$response" | grep "Inserted auth tok" | sed "s/^.*\[//" | sed "s/\].*$//"`
  394. if ! echo "$sig" | egrep -qs "^[0-9a-fA-F]{$KEYBYTES,$KEYBYTES}$"; then
  395.     error "Could not obtain the key signature"
  396. fi
  397. temp=`mktemp`
  398. echo "$sig" > "$temp" || error "Could not create signature file [$HOME/.ecryptfs/$PRIVATE_DIR.sig]"
  399. mv "$temp" "$HOME/.ecryptfs/$PRIVATE_DIR.sig"
  400. temp=`mktemp`
  401. echo "$MOUNTPOINT" > "$temp" || error "Could not create mountpoint file [$HOME/.ecryptfs/$PRIVATE_DIR.mnt]"
  402. mv "$temp" "$HOME/.ecryptfs/$PRIVATE_DIR.mnt"
  403.  
  404. echo
  405. echo "Done configuring."
  406. echo
  407.  
  408. # Skip the tests if we're in bootstrap mode, but exit with the encrypted
  409. # homedir mounted
  410. if [ "$BOOTSTRAP" = "1" ]; then
  411.     # Force the mount here, since the root user has the key loaded,
  412.     # and the calling 'adduser' is about to copy over /etc/skel
  413.     # NOTE: it is the responsibility of 'adduser' to unmount!
  414.     # And ensure that $USER owns the files/dirs we've created as root
  415.     chown $USER:$USER "$CRYPTDIR" /dev/shm/.ecryptfs-$USER
  416.     if [ "$FNEK" = "--fnek" ]; then
  417.         fnek_sig=`tail -n 1 "$HOME/.ecryptfs/$PRIVATE_DIR.sig"`
  418.         sig=`head -n 1 "$HOME/.ecryptfs/$PRIVATE_DIR.sig"`
  419.         sig_opt="ecryptfs_sig=$sig,ecryptfs_fnek_sig=$fnek_sig"
  420.     else
  421.         sig_opt="ecryptfs_sig=$sig"
  422.     fi
  423.     mount -i -t ecryptfs -o "rw,$sig_opt,ecryptfs_cipher=$CIPHER,ecryptfs_key_bytes=$KEYBYTES" "$CRYPTDIR" "$MOUNTPOINT" || error "Could not mount"
  424.     ln -sf /var/lib/ecryptfs/$USER $MOUNTPOINT/.ecryptfs
  425.     for i in auto-mount \
  426.          auto-umount \
  427.          $PRIVATE_DIR.mnt \
  428.          $PRIVATE_DIR.sig \
  429.          wrapped-passphrase;
  430.     do
  431.         [ -e $HOME/.ecryptfs/$i ] && chown $USER:$USER $MOUNTPOINT/.ecryptfs/$i
  432.     done
  433.     chown $USER:$USER /var/lib/ecryptfs/$USER
  434.     chown -h $USER:$USER $MOUNTPOINT/.ecryptfs
  435.     exit 0
  436. fi
  437.  
  438. # Now let's perform some basic mount/write/umount/read sanity testing...
  439. echo "Testing mount/write/umount/read..."
  440. /sbin/mount.ecryptfs_private || error "Could not mount private ecryptfs directory"
  441. temp=`mktemp "$MOUNTPOINT/ecryptfs.test.XXXXXX"` || error_testing "$temp" "Could not create empty file"
  442. random_data=`head -c 16000 /dev/urandom | od -x` || error_testing "$temp" "Could not generate random data"
  443. echo "$random_data" > "$temp" || error_testing "$temp" "Could not write encrypted file"
  444. md5sum1=`md5sum "$temp"` || error_testing "$temp" "Could not read encrypted file"
  445. /sbin/umount.ecryptfs_private || error_testing "$temp" "Could not unmount private ecryptfs directory"
  446. /sbin/mount.ecryptfs_private || error_testing "$temp" "Could not mount private ecryptfs directory (2)"
  447. md5sum2=`md5sum "$temp"` || error_testing "$temp" "Could not read encrypted file (2)"
  448. rm -f "$temp"
  449. # Use ecryptfs-umount-private on the final run, to clear the used keys
  450. # out of the keyring
  451. ecryptfs-umount-private || error_testing "$temp" "Could not unmount private ecryptfs directory (2)"
  452. if [ "$md5sum1" != "$md5sum2" ]; then
  453.     error "Testing failed."
  454. else
  455.     echo "Testing succeeded."
  456. fi
  457.  
  458. echo
  459. echo "Logout, and log back in to begin using your encrypted directory."
  460. echo
  461. exit 0
  462.